package com.xfvape.uid.spring.boot.autoconfigure;

import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import com.xfvape.uid.BitsAllocator;
import com.xfvape.uid.UidGenerator;
import com.xfvape.uid.buffer.RejectedPutBufferHandler;
import com.xfvape.uid.buffer.RejectedTakeBufferHandler;
import com.xfvape.uid.impl.CachedUidGenerator;
import com.xfvape.uid.impl.DefaultUidGenerator;
import com.xfvape.uid.worker.DisposableWorkerIdAssigner;
import com.xfvape.uid.worker.WorkerIdAssigner;
import com.xfvape.uid.worker.dao.WorkerNodeDAO;
import com.xfvape.uid.spring.boot.DefaultRejectedPutBufferHandler;
import com.xfvape.uid.spring.boot.DefaultRejectedTakeBufferHandler;

@Configuration
@ConditionalOnClass({ BitsAllocator.class, UidGenerator.class , MapperScan.class})
@EnableConfigurationProperties(UidGeneratorProperties.class)
@MapperScan("com.xfvape.uid.worker.dao")
public class UidGeneratorAutoConfigration {
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private UidGeneratorProperties uidGeneratorProperties;

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnClass(DisposableWorkerIdAssigner.class)
	public WorkerIdAssigner disposableWorkerIdAssigner(WorkerNodeDAO workerNodeDAO) {
		logger.debug("==============disposableWorkerIdAssigner=================");
		DisposableWorkerIdAssigner disposableWorkerIdAssigner = new DisposableWorkerIdAssigner();
		disposableWorkerIdAssigner.setWorkerNodeDAO(workerNodeDAO);
		return disposableWorkerIdAssigner;
	}
	
	@Bean
	@ConditionalOnMissingBean(RejectedPutBufferHandler.class)
	public RejectedPutBufferHandler rejectedPutBufferHandler() {
		return new DefaultRejectedPutBufferHandler();
	}

	@Bean
	@ConditionalOnMissingBean(RejectedTakeBufferHandler.class)
	public RejectedTakeBufferHandler rejectedTakeBufferHandler() {
		return new DefaultRejectedTakeBufferHandler();
	}
	
	@Bean
	@ConditionalOnBean(WorkerIdAssigner.class)
	@ConditionalOnProperty(name = "spring.uid.cache", havingValue = "true")
	public UidGenerator cachedUidGenerator(WorkerIdAssigner workerIdAssigner,
			RejectedPutBufferHandler rejectedPutBufferHandler, RejectedTakeBufferHandler rejectedTakeBufferHandler) {
		CachedUidGenerator cachedUidGenrator = new CachedUidGenerator();
		if (!StringUtils.isEmpty(uidGeneratorProperties.getTimeBits())) {
			cachedUidGenrator.setTimeBits(uidGeneratorProperties.getTimeBits());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getWorkerBits())) {
			cachedUidGenrator.setWorkerBits(uidGeneratorProperties.getWorkerBits());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getSeqBits())) {
			cachedUidGenrator.setSeqBits(uidGeneratorProperties.getSeqBits());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getEpochStr())) {
			cachedUidGenrator.setEpochStr(uidGeneratorProperties.getEpochStr());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getBoostPower())) {
			cachedUidGenrator.setBoostPower(uidGeneratorProperties.getBoostPower());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getPaddingFactor())) {
			cachedUidGenrator.setPaddingFactor(uidGeneratorProperties.getPaddingFactor());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getScheduleInterval())) {
			cachedUidGenrator.setScheduleInterval(uidGeneratorProperties.getScheduleInterval());
		}
		
		cachedUidGenrator.setWorkerIdAssigner(workerIdAssigner);
		
		if (rejectedPutBufferHandler != null) {
			cachedUidGenrator.setRejectedPutBufferHandler(rejectedPutBufferHandler);
		}
		if (rejectedTakeBufferHandler != null) {
			cachedUidGenrator.setRejectedTakeBufferHandler(rejectedTakeBufferHandler);
		}
		return cachedUidGenrator;
	}

	@Bean
	@ConditionalOnBean(WorkerIdAssigner.class)
	@ConditionalOnMissingBean(UidGenerator.class)
	@ConditionalOnClass(DefaultUidGenerator.class)
	@ConditionalOnProperty(name = "spring.uid.cache", havingValue = "false", matchIfMissing = true)
	public UidGenerator uidGenerator(WorkerIdAssigner workerIdAssigner) {
		DefaultUidGenerator defaultUidGenrator = new DefaultUidGenerator();
		if (!StringUtils.isEmpty(uidGeneratorProperties.getTimeBits())) {
			defaultUidGenrator.setTimeBits(uidGeneratorProperties.getTimeBits());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getWorkerBits())) {
			defaultUidGenrator.setWorkerBits(uidGeneratorProperties.getWorkerBits());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getSeqBits())) {
			defaultUidGenrator.setSeqBits(uidGeneratorProperties.getSeqBits());
		}
		if (!StringUtils.isEmpty(uidGeneratorProperties.getEpochStr())) {
			defaultUidGenrator.setEpochStr(uidGeneratorProperties.getEpochStr());
		}
		defaultUidGenrator.setWorkerIdAssigner(workerIdAssigner);
		return defaultUidGenrator;
	}
}
